﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel; // added ref for this

namespace cs2335lab5
{
    namespace Server
    {
        /// <summary>
        /// Concrete instance of the INetworkManager that implements these functions server-side
        /// </summary>
        [ServiceBehavior(
            InstanceContextMode=InstanceContextMode.PerSession,
            ConcurrencyMode = ConcurrencyMode.Reentrant)]
        public class NetworkManager : Data.INetworkManager
        {
            /// <summary>
            /// shortcut to App's Instance Manager
            /// </summary>
            protected IssueManager IManager
            {
                get
                {
                    return App.Instance().IManager;
                }
            }

            /// <summary>
            /// shortcut to App's User Manager
            /// </summary>
            protected UserManager UManager
            {
                get
                {
                    return App.Instance().UManager;
                }
            }

            /// <summary>
            /// If the user is connected, this should return true
            /// </summary>
            /// <returns></returns>
            public bool Connected()
            {
                App.WriteLine("Verified connection to a client");
                return true;
            }

            /// <summary>
            /// Passes the Authenticate call to the user manager
            /// </summary>
            /// <param name="user"></param>
            /// <returns></returns>
            public Data.User Authenticate(Data.User user)
            {
                App.WriteLine(user.ID + " called Authenticate()");

                // authenticate the user
                return UManager.Authenticate(user);
            }

            /// <summary>
            /// Passes the Log Out call to the user manager
            /// </summary>
            /// <param name="user"></param>
            public void LogOut(Data.User user)
            {
                App.WriteLine(user.ID + " called LogOut()");

                UManager.LogOut(user);
            }

            /// <summary>
            /// Get a specific user
            /// </summary>
            /// <param name="name"></param>
            /// <returns></returns>
            public Data.User GetUser(string name)
            {
                // use a copy constructor here
                Data.User search = UManager.FindUser(name);
                if (search == null)
                {
                    return null;
                }

                Data.User result = new Data.User(UManager.FindUser(name));
                if (result != null && result.Password != null)
                {
                    result.Password = null;
                }
                return result;
            }

            /// <summary>
            /// Get a specific issue
            /// </summary>
            /// <param name="id"></param>
            /// <returns></returns>
            public Data.Issue GetIssue(Int64? id)
            {
                Data.Issue search = IManager.FindIssue(id);

                // if we couldn't find an issue with that ID, return null
                if (search == null)
                {
                    return null;
                }

                // otherwise copy it, pass it over
                return new Data.Issue(IManager.FindIssue(id));
            }

            /// <summary>
            /// Return the user list
            /// </summary>
            /// <returns></returns>
            public Dictionary<string, Data.User> GetUserList()
            {
                return UManager.Users;
            }

            /// <summary>
            /// Return the issue list
            /// </summary>
            /// <returns></returns>
            public Dictionary<Int64?, Data.Issue> GetIssueList()
            {
                return IManager.Issues;
            }

            /// <summary>
            /// Possible callback function?
            /// </summary>
            /// <param name="user"></param>
            /// <returns></returns>
            public bool IssueStateChanged(Data.User user)
            {
                // TODO
                return false;
            }

            /// <summary>
            /// Possible callback function?
            /// </summary>
            /// <param name="user"></param>
            /// <returns></returns>
            public bool UserStateChanged(Data.User user)
            {
                // TODO
                return false;
            }

            /// <summary>
            /// Passes the Register call to the user manager
            /// </summary>
            /// <param name="user"></param>
            /// <returns></returns>
            public Data.User Register(Data.User user)
            {
                App.WriteLine(user.ID + " called Register()");

                return UManager.AddUser(null, user);
            }

            /// <summary>
            /// Adds a user. Lets an admin create another admin user in one step.
            /// </summary>
            /// <param name="actor">User creating a user</param>
            /// <param name="user">User details to be created</param>
            /// <returns></returns>
            public Data.User AddUser(Data.User actor, Data.User user)
            {
                return UManager.AddUser(actor, user);
            }

            /// <summary>
            /// Updates a user. Only the current user or an administrator can update a user.
            /// Only an admin can change a user's access. The first user created on a 
            /// system is automatically an administrator.
            /// </summary>
            /// <param name="actor"></param>
            /// <param name="reciever"></param>
            public Data.User UpdateUser(Data.User actor, Data.User user)
            {
                return UManager.UpdateUser(actor, user);
            }

            /// <summary>
            /// Adds a new issue
            /// </summary>
            /// <param name="actor">User adding the issue</param>
            /// <param name="issue">The issue the user created</param>
            /// <returns></returns>
            public Data.Issue AddIssue(Data.User actor, Data.Issue issue)
            {
                return IManager.AddIssue(actor, issue);
            }

            /// <summary>
            /// Updates an issue. Anyone can do this?
            /// </summary>
            /// <param name="actor">User updating the issue</param>
            /// <param name="issue">The user's updated issue</param>
            public Data.Issue UpdateIssue(Data.User actor, Data.Issue issue)
            {
                return IManager.UpdateIssue(actor, issue);
            }

            /// <summary>
            /// Deletes a user
            /// </summary>
            /// <param name="key"></param>
            public void DeleteUser(string key)
            {
                UManager.Delete(key);
            }

            /// <summary>
            /// Deletes an issue.
            /// </summary>
            /// <param name="key"></param>
            public void DeleteIssue(Int64? key)
            {
                IManager.Delete(key);
            }

            /// <summary>
            /// Function to change a user's access rights. 
            /// </summary>
            /// <param name="actor"></param>
            /// <param name="reciever"></param>
            /// <param name="access"></param>
            public void SetUserPrivileges(Data.User actor, Data.User reciever, Data.User.Privileges access)
            {
                // TODO
                throw new NotImplementedException();
            }

            /// <summary>
            /// Forcibly logs a user out of the system. It's fun!
            /// </summary>
            /// <param name="actor"></param>
            /// <param name="reciever"></param>
            public void KickUser(Data.User actor, Data.User reciever)
            {
                // TODO
                throw new NotImplementedException();
            }
        }
    }
}